﻿using System;
using UnityEngine;

// Token: 0x02000130 RID: 304
[AddComponentMenu("RVP/C#/Drivetrain/Transmission/Gearbox Transmission", 0)]
[DisallowMultipleComponent]
public class GearboxTransmission : Transmission
{
	// Token: 0x06000598 RID: 1432 RVA: 0x0002BCFD File Offset: 0x00029EFD
	public override void Start()
	{
		base.Start();
		this.currentGear = Mathf.Clamp(this.startGear, 0, this.gears.Length - 1);
		this.GetFirstGear();
	}

	// Token: 0x06000599 RID: 1433 RVA: 0x0002BD28 File Offset: 0x00029F28
	private void Update()
	{
		if (!this.automatic)
		{
			if (this.vp.upshiftPressed && this.currentGear < this.gears.Length - 1)
			{
				this.Shift(1);
			}
			if (this.vp.downshiftPressed && this.currentGear > 0)
			{
				this.Shift(-1);
			}
		}
	}

	// Token: 0x0600059A RID: 1434 RVA: 0x0002BD90 File Offset: 0x00029F90
	private void FixedUpdate()
	{
		this.health = Mathf.Clamp01(this.health);
		this.shiftTime = Mathf.Max(0f, this.shiftTime - Time.timeScale * TimeMaster.inverseFixedTimeFactor);
		this.curGearRatio = this.gears[this.currentGear].ratio;
		float num = this.targetDrive.feedbackRPM / Mathf.Abs(this.curGearRatio);
		int num2 = 1;
		int num3 = 1;
		while ((this.skipNeutral || this.automatic) && this.gears[Mathf.Clamp(this.currentGear + num2, 0, this.gears.Length - 1)].ratio == 0f && this.currentGear + num2 != 0 && this.currentGear + num2 != this.gears.Length - 1)
		{
			num2++;
		}
		while ((this.skipNeutral || this.automatic) && this.gears[Mathf.Clamp(this.currentGear - num3, 0, this.gears.Length - 1)].ratio == 0f && this.currentGear - num3 != 0 && this.currentGear - num3 != 0)
		{
			num3++;
		}
		this.upperGear = this.gears[Mathf.Min(this.gears.Length - 1, this.currentGear + num2)];
		this.lowerGear = this.gears[Mathf.Max(0, this.currentGear - num3)];
		if (this.maxRPM == -1f)
		{
			this.maxRPM = this.targetDrive.curve.keys[this.targetDrive.curve.length - 1].time;
			if (this.autoCalculateRpmRanges)
			{
				this.CalculateRpmRanges();
			}
		}
		this.newDrive.curve = this.targetDrive.curve;
		if (this.curGearRatio == 0f || this.shiftTime > 0f)
		{
			this.newDrive.rpm = 0f;
			this.newDrive.torque = 0f;
		}
		else
		{
			this.newDrive.rpm = ((!this.automatic || !this.skidSteerDrive) ? this.targetDrive.rpm : (Mathf.Abs(this.targetDrive.rpm) * Mathf.Sign(this.vp.accelInput - ((!this.vp.brakeIsReverse) ? 0f : (this.vp.brakeInput * (1f - this.vp.burnout)))))) / this.curGearRatio;
			this.newDrive.torque = Mathf.Abs(this.curGearRatio) * this.targetDrive.torque;
		}
		this.upshiftDifference = this.gears[this.currentGear].maxRPM - this.upperGear.minRPM;
		this.downshiftDifference = this.lowerGear.maxRPM - this.gears[this.currentGear].minRPM;
		if (this.automatic && this.shiftTime == 0f && this.vp.groundedWheels > 0)
		{
			if (!this.skidSteerDrive && this.vp.burnout == 0f)
			{
				if (Mathf.Abs(this.vp.localVelocity.z) > 1f || this.vp.accelInput > 0f || (this.vp.brakeInput > 0f && this.vp.brakeIsReverse))
				{
					if (this.currentGear < this.gears.Length - 1 && (this.upperGear.minRPM + this.upshiftDifference * ((this.curGearRatio >= 0f) ? this.shiftThreshold : Mathf.Min(1f, this.shiftThreshold)) - num <= 0f || (this.curGearRatio <= 0f && this.upperGear.ratio > 0f && (!this.vp.reversing || (this.vp.accelInput > 0f && this.vp.localVelocity.z > this.curGearRatio * 10f)))) && (this.vp.brakeInput <= 0f || !this.vp.brakeIsReverse || this.upperGear.ratio < 0f) && (this.vp.localVelocity.z >= 0f || this.vp.accelInput != 0f))
					{
						this.Shift(1);
					}
					else if (this.currentGear > 0 && (num - (this.lowerGear.maxRPM - this.downshiftDifference * this.shiftThreshold) <= 0f || (this.curGearRatio >= 0f && this.lowerGear.ratio < 0f && (this.vp.reversing || ((this.vp.accelInput < 0f || (this.vp.brakeInput > 0f && this.vp.brakeIsReverse)) && this.vp.localVelocity.z < this.curGearRatio * 10f)))) && (this.vp.accelInput <= 0f || this.lowerGear.ratio > 0f) && (this.lowerGear.ratio > 0f || this.vp.localVelocity.z < 1f))
					{
						this.Shift(-1);
					}
				}
			}
			else if (this.currentGear != this.firstGear)
			{
				this.ShiftToGear(this.firstGear);
			}
		}
		base.SetOutputDrives(this.curGearRatio);
	}

	// Token: 0x0600059B RID: 1435 RVA: 0x0002C3F8 File Offset: 0x0002A5F8
	public void Shift(int dir)
	{
		if (this.health > 0f)
		{
			this.shiftTime = this.shiftDelay;
			this.currentGear += dir;
			while ((this.skipNeutral || this.automatic) && this.gears[Mathf.Clamp(this.currentGear, 0, this.gears.Length - 1)].ratio == 0f && this.currentGear != 0 && this.currentGear != this.gears.Length - 1)
			{
				this.currentGear += dir;
			}
			this.currentGear = Mathf.Clamp(this.currentGear, 0, this.gears.Length - 1);
		}
	}

	// Token: 0x0600059C RID: 1436 RVA: 0x0002C4C0 File Offset: 0x0002A6C0
	public void ShiftToGear(int gear)
	{
		if (this.health > 0f)
		{
			this.shiftTime = this.shiftDelay;
			this.currentGear = Mathf.Clamp(gear, 0, this.gears.Length - 1);
		}
	}

	// Token: 0x0600059D RID: 1437 RVA: 0x0002C4F8 File Offset: 0x0002A6F8
	public void CalculateRpmRanges()
	{
		bool flag = false;
		if (!Application.isPlaying)
		{
			GasMotor componentInChildren = F.GetTopmostParentComponent<VehicleParent>(base.transform).GetComponentInChildren<GasMotor>();
			if (componentInChildren)
			{
				this.maxRPM = componentInChildren.torqueCurve.keys[componentInChildren.torqueCurve.length - 1].time;
			}
			else
			{
				Debug.LogError("There is no <GasMotor> in the vehicle to get RPM info from.", this);
				flag = true;
			}
		}
		if (!flag)
		{
			float num = this.maxRPM * 1000f;
			for (int i = 0; i < this.gears.Length; i++)
			{
				float ratio = this.gears[Mathf.Max(i - 1, 0)].ratio;
				float ratio2 = this.gears[Mathf.Min(i + 1, this.gears.Length - 1)].ratio;
				if (this.gears[i].ratio < 0f)
				{
					this.gears[i].minRPM = num / this.gears[i].ratio;
					if (ratio2 == 0f)
					{
						this.gears[i].maxRPM = 0f;
					}
					else
					{
						this.gears[i].maxRPM = num / ratio2 + (num / ratio2 - this.gears[i].minRPM) * 0.5f;
					}
				}
				else if (this.gears[i].ratio > 0f)
				{
					this.gears[i].maxRPM = num / this.gears[i].ratio;
					if (ratio == 0f)
					{
						this.gears[i].minRPM = 0f;
					}
					else
					{
						this.gears[i].minRPM = num / ratio - (this.gears[i].maxRPM - num / ratio) * 0.5f;
					}
				}
				else
				{
					this.gears[i].minRPM = 0f;
					this.gears[i].maxRPM = 0f;
				}
				this.gears[i].minRPM *= 0.55f;
				this.gears[i].maxRPM *= 0.55f;
			}
		}
	}

	// Token: 0x0600059E RID: 1438 RVA: 0x0002C740 File Offset: 0x0002A940
	public void GetFirstGear()
	{
		for (int i = 0; i < this.gears.Length; i++)
		{
			if (this.gears[i].ratio == 0f)
			{
				this.firstGear = i + 1;
				break;
			}
		}
	}

	// Token: 0x040007EB RID: 2027
	public Gear[] gears;

	// Token: 0x040007EC RID: 2028
	public int startGear;

	// Token: 0x040007ED RID: 2029
	[NonSerialized]
	public int currentGear;

	// Token: 0x040007EE RID: 2030
	private int firstGear;

	// Token: 0x040007EF RID: 2031
	[NonSerialized]
	public float curGearRatio;

	// Token: 0x040007F0 RID: 2032
	public bool skipNeutral;

	// Token: 0x040007F1 RID: 2033
	[Tooltip("Calculate the RPM ranges of the gears in play mode.  This will overwrite the current values")]
	public bool autoCalculateRpmRanges = true;

	// Token: 0x040007F2 RID: 2034
	[Tooltip("Number of physics steps a shift should last")]
	public float shiftDelay;

	// Token: 0x040007F3 RID: 2035
	[NonSerialized]
	public float shiftTime;

	// Token: 0x040007F4 RID: 2036
	private Gear upperGear;

	// Token: 0x040007F5 RID: 2037
	private Gear lowerGear;

	// Token: 0x040007F6 RID: 2038
	private float upshiftDifference;

	// Token: 0x040007F7 RID: 2039
	private float downshiftDifference;

	// Token: 0x040007F8 RID: 2040
	[Tooltip("Multiplier for comparisons in automatic shifting calculations, should be 2 in most cases")]
	public float shiftThreshold;
}
